Imports BikiSoft.Comm.Comm_Bikirom
Namespace Comm
    Friend Class Comm_Bikirom
        Shared m_lngHandle As Integer = 0

    End Class

    Friend Class Comm_Frame
        Public Enum BikiFrameType As Byte
            ID_CONSULT_PASS = &H91
            ID_CONSULT_INTEGRATED = &H92
            ID_FLASH_DATA = &H80
            ID_EEPROM_DATA = &H82
            ID_GENERAL_SPECIFIC = &H55
            ID_LAST_COMMAND_STATUS = &HAA
            ID_RUN_COMMAND = &HE0
            ID_BOOTLOADER = &H70
            ID_ATMEL = &H2A
            ID_PC = &H1A
            ID_ECU = &HA
        End Enum
        Public Enum BikiFrameResponse As Byte
            CMD_OK = &H1
            CMD_FAILED = &H2
            CMD_CRC_FAILED = &H3
            CMD_NEXT = &H4
            SIG_FAILED = &H5
            BUFFER_FULL = &H6
            CMD_INCOMPLETE = &H7
            CMD_UNKNOWN_SENDER = &H8
            CMD_UNKNOWN_RECIVER = &H9
            CMD_UNKNOWN = &H10
            CMD_BAD_HEADS = &HA
            CMD_TIMEOUT = &H1E
            SEC_BAD_CODE = &H30
            SEC_FUNCTION_LOCKED = &H31
            FLASH_WRITE_TIMEOUT = &H1F
        End Enum
        Public Enum BikiFrameAction As Byte
            WRITE = &H55
            READ = &HAA
            RUN_ERASEALL = &H80
            RUN_ERASESECTOR = &H88
            CMD_STOP = &HB
            CMD_GO = &HC
        End Enum

        Dim m_Frame As Byte() = Nothing
        Dim m_Action As BikiFrameAction = Nothing
        Dim m_Response As BikiFrameType = Nothing

        Sub New(ByVal fType As BikiFrameType, Optional ByVal Address As UInt32 = 0, Optional ByVal Action As BikiFrameAction = Nothing, Optional ByVal Payload As Byte() = Nothing, Optional ByVal Response As BikiFrameType = BikiFrameType.ID_LAST_COMMAND_STATUS)
            Dim arrCmd() As Byte = Nothing
            Select Case fType
                Case BikiFrameType.ID_FLASH_DATA, BikiFrameType.ID_EEPROM_DATA
                    If Action = BikiFrameAction.WRITE Then
                        ReDim arrCmd(UBound(Payload) + 17)
                        Array.Copy(Payload, 0, arrCmd, 13, Payload.Length)
                    ElseIf Action = BikiFrameAction.READ Then
                        ReDim arrCmd(16)
                    End If
                    If Not IsNothing(arrCmd) Then
                        arrCmd(6) = fType
                        arrCmd(7) = Action
                        arrCmd(8) = (Address \ &H10000) And &HFF
                        arrCmd(9) = (Address \ &H100) And &HFF
                        arrCmd(10) = Address And &HFF
                        arrCmd(11) = (Payload.Length \ &H100) And &HFF
                        arrCmd(12) = Payload.Length And &HFF
                        frameHeadFootCrc(arrCmd)
                    End If
                Case BikiFrameType.ID_RUN_COMMAND
                    Select Case Action
                        Case BikiFrameAction.RUN_ERASEALL
                            ReDim arrCmd(11)
                        Case BikiFrameAction.RUN_ERASESECTOR
                            ReDim arrCmd(14)
                            arrCmd(8) = (Address \ &H10000) And &HFF
                            arrCmd(9) = (Address \ &H100) And &HFF
                            arrCmd(10) = Address And &HFF
                    End Select
                    If Not IsNothing(arrCmd) Then
                        arrCmd(6) = fType
                        arrCmd(7) = Action
                        frameHeadFootCrc(arrCmd)
                    End If
                Case BikiFrameType.ID_CONSULT_INTEGRATED, BikiFrameType.ID_CONSULT_PASS
                    Select Case Action
                        Case BikiFrameAction.CMD_GO, BikiFrameAction.CMD_STOP
                            ReDim arrCmd(11)
                            arrCmd(6) = fType
                            arrCmd(7) = Action
                    End Select
            End Select
            m_Action = Action
            m_Frame = arrCmd
            m_Response = Response
        End Sub

        ''' <summary>
        ''' Sends the frame off, and passes back the array of the response if nothing than Last Command status. will throw any exceptions generated also. they need to be cought
        ''' </summary>
        ''' <param name="Array"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Friend Function Send(Optional ByRef Array As Byte() = Nothing) As Boolean

        End Function

        Private Sub frameHeadFootCrc(ByRef frame As Byte())
            If Not IsNothing(frame) AndAlso frame.Length > 6 Then
                frame(0) = &HAA
                frame(1) = &HA5
                frame(2) = &H2A
                frame(3) = &H1A
                frame(4) = ((frame.Length - 10) \ &H100) And &HFF
                frame(5) = (frame.Length - 10) And &HFF
                frame(UBound(frame) - 1) = &H55
                frame(UBound(frame)) = &H5A
                crcCalculate(frame)
            End If
        End Sub

        ''' <summary>
        ''' This function Calculates the CRC of a BikiUSB packet and places it in the CRC location of the frame.
        ''' </summary>
        ''' <param name="Buffer"></param>
        ''' <remarks></remarks>
        Private Sub crcCalculate(ByRef Buffer As Byte())
            Dim i As Integer
            Dim cr As UShort = 0
            For i = 6 To UBound(Buffer) - 4
                cr = crc(Buffer(i), cr)
            Next
            Buffer(UBound(Buffer) - 3) = (cr \ &H100) And &HFF
            Buffer(UBound(Buffer) - 2) = cr And &HFF
        End Sub
        ''' <summary>
        ''' This function Validates the CRC of a BikiUSB packet
        ''' </summary>
        ''' <param name="Buffer"></param>
        ''' <returns>true is a valid packet</returns>
        ''' <remarks></remarks>
        Private Function crcValidate(ByRef Buffer As Byte()) As Boolean
            Dim i As Integer
            Dim cr As UShort = 0
            For i = 6 To UBound(Buffer) - 4
                cr = crc(Buffer(i), cr)
            Next
            If Buffer(UBound(Buffer) - 3) = ((cr \ &H100) And &HFF) And _
               Buffer(UBound(Buffer) - 2) = (cr And &HFF) _
            Then
                Return True
            Else
                Return False
            End If
        End Function

        Public Function crc(ByVal cd As Byte, ByRef oldCrc As UShort) As UShort
            Dim i As Integer

            oldCrc = oldCrc Xor cd

            For i = 0 To 7
                If (oldCrc And 1) Then
                    oldCrc = (oldCrc \ 2) Xor &HA001
                Else
                    oldCrc = (oldCrc \ 2)
                End If
            Next

            Return oldCrc
        End Function

    End Class
End Namespace